package cordova.plugin.zmq;

import java.util.Random;
import java.io.UnsupportedEncodingException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.text.Html;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import cordova.plugin.zmq.service.Client;
import cordova.plugin.zmq.service.ISocketResponse;
import cordova.plugin.zmq.service.Packet;

/**
 * This class echoes a string called from JavaScript.
 */

public class ZMQPlugin extends CordovaPlugin {

    public static final String iconname = "icon";  //通知栏图片名称
    private static ZMQPlugin instance;
    private static Activity cordovaActivity;
    public NotificationManager mNotificationManager;  //通知管理器
    public android.content.Context m_context;  //上下文

    private static final long Send_HeartTime = 30000;  //心跳间隔时间
    private Client user = null;
    private boolean sendable = true; //是否发生心跳标识
    private ExecutorService sendPool;  //心跳线程

    private String url, connectId, token;   //链接地址，用户Id
    private int port;  //端口
    private CallbackContext mCallbackContext;

    public ZMQPlugin() {
        instance = this;
    }

    @Override
    public void initialize(CordovaInterface cordova, CordovaWebView webView) {
        super.initialize(cordova, webView);
        cordovaActivity = cordova.getActivity();
        m_context = cordovaActivity.getApplicationContext();
        mNotificationManager = (NotificationManager) m_context.getSystemService(android.content.Context.NOTIFICATION_SERVICE);  //实例化通知栏
    }

    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        mCallbackContext = callbackContext;

        if (action.equalsIgnoreCase("zmqConnect")) {  //链接
            if (sendPool == null)
                sendPool = Executors.newScheduledThreadPool(1);

            if (user == null) {
                // user = new Client(m_context, socketListener);
                user = Client.getInstance();
            }
            user.setContext(m_context);
            user.setRespListener(socketListener);
            sendable = true;
            this.zmqConnect(args);
            return true;
        } else if (action.equalsIgnoreCase("zmqSendToPeer")) {  //发送
            this.zmqSendToPeer(args.getString(0));
            return true;
        } else if (action.equalsIgnoreCase("zmqRecvFromPeer")) {
            return true;
        } else {  //断开
//            this.zmqDisConnect(args);
            return true;
        }
    }

    /**
     * 连接
     *
     * @param args 地址及ID
     */
    private void zmqConnect(final JSONArray args) {

        try {
            JSONObject hostname = new JSONObject(args.getJSONObject(0).getString("url"));
            url = hostname.getString("ip");
            port = hostname.getInt("port");
            connectId = args.getJSONObject(0).getString("id");
            token = args.getJSONObject(0).getString("token");
            user.open(url, port);

//            sendIdMessage();
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    /**
     * 发送setId
     */
    private void sendIdMessage() {
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("command", "setId");
            jsonObject.put("id", connectId);
            jsonObject.put("token", token);
            Packet packet = new Packet();
            packet.pack(jsonObject.toString());
            user.send(packet);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    /**
     * 心跳发送线程
     */
    private void sendEmpty() {
        sendPool.execute(new Runnable() {
            @Override
            public void run() {
                while (sendable) {
                    try {
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put("command", "HeartBeat");
                        Packet packet = new Packet();
                        packet.pack(jsonObject.toString());
                        user.send(packet);
                        Thread.sleep(Send_HeartTime);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    /**
     * 发送
     *
     * @param message 发送内容
     */
    private void zmqSendToPeer(final String message) {
        Packet packet = new Packet();
        packet.pack(message.toString());
        user.send(packet);
    }

    /**
     * 处理接收到的消息
     */
    private ISocketResponse socketListener = new ISocketResponse() {

        @Override
        public void onSocketResponse(final String content) {
            cordovaActivity.runOnUiThread(new Runnable() {
                public void run() {
                    JSONObject success = new JSONObject();
                    if (content.equals("200")) {
//                        mHandler.sendEmptyMessage(1);
                    } else {
                        try {
                            success.put("message", content);
                            success.put("code", 200);
                            JSONObject jsonObject = new JSONObject(content);
                            switch (jsonObject.getInt("type")) {
                                case 21:
                                    openPushService(success.toString());
                                    receiveNotificationMsg(success.toString());
                                    break;

                                case 2:
                                    openPushService(success.toString());
                                    break;

                                default:
                                    showMessage(success.toString());
                                    break;
                            }
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
        }

        /**
         * 打开通知栏
         * @param message
         */
        private void openPushService(String message) {
            Intent intent = new Intent(cordovaActivity, ShowNotificationReceiver.class);
            intent.putExtra("message", message);
            cordovaActivity.sendBroadcast(intent);
        }

        /**
         * 展示普通消息
         * @param msg
         */
        private void showMessage(String msg) {
            Intent intenta = new Intent(cordovaActivity, ZMQPluginBroadcastReceiver.class);
            intenta.setAction(ZMQPluginBroadcastReceiver.RECEIVE);
            intenta.putExtra("message", msg);
            // 发送广播通知收到信息
            cordovaActivity.sendBroadcast(intenta);
        }


        @Override
        public void onResendId() {
            sendable = false;
            sendIdMessage();
        }

        @Override
        public void onSetEmptyMsg() {
            sendable = true;
            sendEmpty();
        }

        @Override
        public void onCallBackStatus(int method, int status) {
            JSONObject jsonObject = new JSONObject();
            try {
                switch (method) {
                    case 1:  //连接状态
                        if (status == 1 << 3) {
                            jsonObject.put("message", "链接成功");
                            jsonObject.put("code", 200);
                            PluginResult plResult = new PluginResult(PluginResult.Status.OK, jsonObject);
                            mCallbackContext.sendPluginResult(plResult);

                            sendIdMessage();
                        } else {
                            jsonObject.put("message", "链接失败");
                            jsonObject.put("code", 516);
                            PluginResult plResult = new PluginResult(PluginResult.Status.ERROR, jsonObject);
                            mCallbackContext.sendPluginResult(plResult);
                        }
                        break;

                    case 2:  //发送状态
                        if (status == 1) {
                            jsonObject.put("message", "发送成功");
                            jsonObject.put("code", 200);
                            PluginResult plResult = new PluginResult(PluginResult.Status.OK, jsonObject);
                            mCallbackContext.sendPluginResult(plResult);
                        } else {
                            jsonObject.put("message", "发送失败");
                            jsonObject.put("code", 516);
                            PluginResult plResult = new PluginResult(PluginResult.Status.ERROR, jsonObject);
                            mCallbackContext.sendPluginResult(plResult);
                        }
                        break;

                    case 3:  //断开连接状态
                        if (status == 1 << 1) {
                            jsonObject.put("message", "断开链接成功");
                            jsonObject.put("code", 200);
                            PluginResult plResult = new PluginResult(PluginResult.Status.OK, jsonObject);
                            mCallbackContext.sendPluginResult(plResult);
                        } else {
                            jsonObject.put("message", "断开链接失败");
                            jsonObject.put("code", 516);
                            PluginResult plResult = new PluginResult(PluginResult.Status.ERROR, jsonObject);
                            mCallbackContext.sendPluginResult(plResult);
                        }
                        break;
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    };

    /**
     * 断开连接
     */
    private void zmqDisConnect(JSONArray args) {
        try {
            sendable = false;
            if (sendPool != null)
                sendPool.shutdown();

            if (user != null)
                user.close();
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("message", "断开链接成功");
            jsonObject.put("code", 200);
            PluginResult plResult = new PluginResult(PluginResult.Status.OK, jsonObject);
            mCallbackContext.sendPluginResult(plResult);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 普通消息
     *
     * @param message
     */
    public static void receiveGeneralMsg(String message) {
        try {
            JSONObject data = new JSONObject(message);
            String format = "cordova.fireDocumentEvent('zmq.messages',%s)";
            final String js = String.format(format, data.toString());
            cordovaActivity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    instance.webView.loadUrl("javascript:" + js);
                }
            });
        } catch (JSONException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 通知消息
     *
     * @param msg
     */
    public static void receiveNotificationMsg(String msg) {
        try {
            JSONObject json = new JSONObject(msg);
            String format = "cordova.fireDocumentEvent('zmq.notification',%s)";
            final String js = String.format(format, json.toString());
            cordovaActivity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    instance.webView.loadUrl("javascript:" + js);
                }
            });
        } catch (JSONException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 打开通知栏
     *
     * @param contents 内容{title:'通知标题',content:'通知内容'}
     */
    private void openNotification(JSONObject contents, String msg) {

        try {
            JSONObject jsonObject = new JSONObject(contents.getString("body"));
            String title = jsonObject.getString("title");
            String content = jsonObject.getString("content");
            if (content != null && title != null) {
                Intent intenta = new Intent();
                intenta.setAction(ZMQPluginBroadcastReceiver.ACTION);
                intenta.putExtra("msg", msg);
                int id = (int) (Math.random() * 65000);
                PendingIntent m_PendingIntent = PendingIntent.getBroadcast(this.cordova.getActivity(), id, intenta, PendingIntent.FLAG_UPDATE_CURRENT);
                int iconResID = m_context.getResources().getIdentifier(iconname, "drawable", m_context.getPackageName());
                Notification notification = new NotificationCompat.Builder(cordovaActivity)
                        .setContentTitle(title)
                        .setContentText(Html.fromHtml(content))
                        .setDefaults(Notification.DEFAULT_ALL) //设置默认铃声，震动等
                        .setSmallIcon(iconResID)
                        .setContentIntent(m_PendingIntent)
                        .setVibrate(new long[]{100, 400, 100, 400})
                        .setAutoCancel(true)
                        .setOngoing(true)
                        .setWhen(System.currentTimeMillis())
                        .build();
                mNotificationManager.notify(id, notification);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
